package com.shenjialin.Tank;

import com.shenjialin.Game.Bullet;
import com.shenjialin.Game.Explode;
import com.shenjialin.Game.GameFrame;
import com.shenjialin.Map.MapTile;
import com.shenjialin.util.*;

import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * 坦克类
 */
public abstract class Tank {

    protected String name;
    // 四个方向
    public static final int DIR_UP = 0;
    public static final int DIR_DOWN = 1;
    public static final int DIR_LEFT = 2;
    public static final int DIR_RIGHT = 3;
    // 半径
    public static final int RADIUS = 24;
    // 默认的速度 每一帧移动的像素
    public static final int DEFAULT_SPEED = 20;
    //坦克的状态
    public static final int STATE_STAND = 0;
    public static final int STATE_MOVE = 1;
    public static final int STATE_DIE = 2;
    // 坦克的初始生命
    public static final int DEFAULT_HP = 1000;
    public static final int DEFAULT_ATK = 100;




    // 坦克中心点  坐标
    protected int x,y;
    protected int preX,preY;
    protected int hp = DEFAULT_HP;
    protected int atk = DEFAULT_ATK;
    protected int def;
    protected int speed = DEFAULT_SPEED;
    protected int dir;
    protected int state = STATE_STAND;
    protected Color color;
    protected boolean isEnemy = false;



    //TODO 炮弹
    protected List<Bullet> bullets = new ArrayList<>();

    // 使用容器来保存当前坦克上的 所有的爆炸效果

    private List<Explode> explodes = new ArrayList<Explode>();


    protected BloodBar bar = new BloodBar();

    public Tank(int x, int y, int dir) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        color = MyUtil.getRandomColor();
        name = MyUtil.getName();
    }
    public Tank() {

    }

    // 用于创建敌人坦克的方法


    /**
     * 使用系统的方式 绘制坦克
     * @param g
     */
    protected void drawTank(Graphics g) {
        g.setColor(color);

        // 绘制坦克的圆
        g.fillOval(x-RADIUS,y-RADIUS,RADIUS<<1,RADIUS<<1);
        // 绘制
        int endX = x;
        int endY = y;
        switch (dir) {
            case DIR_UP:
                endY = y - RADIUS*2;
                g.drawLine(x,y,endX,endY);
                g.drawLine(x-1,y,endX-1,endY);
                g.drawLine(x+1,y,endX+1,endY);
                break;
            case DIR_DOWN:
                endY = y + RADIUS*2;
                g.drawLine(x,y,endX,endY);
                g.drawLine(x-1,y,endX-1,endY);
                g.drawLine(x+1,y,endX+1,endY);
                break;
            case DIR_LEFT:
                endX = x - RADIUS*2;
                g.drawLine(x,y,endX,endY);
                g.drawLine(x,y-1,endX,endY-1);
                g.drawLine(x,y+1,endX,endY+1);
                break;
            case DIR_RIGHT:
                endX = x + RADIUS*2;
                g.drawLine(x,y,endX,endY);
                g.drawLine(x,y-1,endX,endY-1);
                g.drawLine(x,y+1,endX,endY+1);
                break;
        }
    }

    // 坦克的逻辑处理
    protected void logic() {
        switch (state) {
            case STATE_STAND:
                break;
            case STATE_MOVE:
                move();
                break;
            case STATE_DIE:
                break;
        }
    }

    // 坦克移动的功能
    protected void move() {
        preX = x;
        preY = y;
        switch (dir) {// 不同方向具有不同的移动逻辑
            case DIR_UP:
                y -= speed;
                if(y < RADIUS + GameFrame.titleBarH) {
                    y = RADIUS + GameFrame.titleBarH;
                }
                break;
            case DIR_DOWN:
                y += speed;
                if(y > Constant.FRAME_HEIGHT - RADIUS) {
                    y = Constant.FRAME_HEIGHT - RADIUS;
                }
                break;
            case DIR_LEFT:
                x -= speed;
                if(x < RADIUS) {
                    x = RADIUS;
                }
                break;
            case DIR_RIGHT:
                x += speed;
                if(x > Constant.FRAME_WIDTH - RADIUS) {
                    x = Constant.FRAME_WIDTH - RADIUS;
                }
                break;
        }
    }
    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getDef() {
        return def;
    }

    public void setDef(int def) {
        this.def = def;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public List getBullets() {
        return bullets;
    }

    public void setBullets(List bullets) {
        this.bullets = bullets;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    /**
     * 坦克的功能 坦克开火的方法
     * 创建一个子弹对象 子弹对象的属性信息 通过坦克的信息获得
     * 然后将创建的子弹 添加到 坦克管理 的容器
     */
    public void fire() {
        int bulletX = x;
        int bulletY = y;
        switch (dir) {
            case DIR_UP:
                bulletY -= RADIUS;
                break;
            case DIR_DOWN:
                bulletY += RADIUS;
                break;
            case DIR_LEFT:
                bulletX -= RADIUS;
                break;
            case DIR_RIGHT:
                bulletX += RADIUS;
                break;
        }
        //
        Bullet bullet = BulletsPool.get();
        bullet.setBulletType(Bullet.BULLET_TYPE0);
        bullet.setX(bulletX);
        bullet.setY(bulletY);
        bullet.setDir(dir);
        bullet.setSpeed(speed * 2);
        bullet.setAtk(atk);
        bullet.setColor(color);
        bullet.setVisible(true);
        //= new Bullet(bulletX,bulletY,dir,atk,color);
        bullets.add(bullet);
    }

    /**
     * 将当前坦克发射的所有子弹绘制出来
     * @param g
     */
    protected void drawBullets(Graphics g) {
        for (Bullet bullet : bullets) {
            bullet.draw(g);
        }
        // 遍历所有的子弹 将不可见的子弹移除 并返回对象池
        for (int i = 0; i < bullets.size(); ++i) {
            Bullet bullet = bullets.get(i);
            if(!bullet.isVisible()){
                Bullet remove = bullets.remove(i);
                i--;
                BulletsPool.theReturn(remove);
            }
        }
    }

    // 坦克和子弹的碰撞方法
    public void collideBullets(List<Bullet> bullets) {
        // 遍历所有的子弹 依次和当前的坦克进行碰撞检测
        for (Bullet bullet : bullets) {
            int bulletX = bullet.getX();
            int bulletY = bullet.getY();
            // 子弹和坦克发生了碰撞
            if(bullet.getBulletType() == Bullet.BULLET_TYPE0) {
                if (MyUtil.isCollide(x, y, RADIUS, bulletX, bulletY)){
                    // 子弹消失
                    bullet.setVisible(false);
                    // 坦克收到伤害
                    hurt(bullet);
                    // 添加爆炸效果
                    addExplode(x, y );
                }
            }
            if(bullet.getBulletType() == Bullet.BULLET_TYPE1) {
                if(MyUtil.isCollide(x, y, RADIUS + Bullet.RADIUS1, bulletX, bulletY)) {
                    // 坦克收到伤害
                    hurt(bullet);
                    // 添加爆炸效果
                    addExplode(x, y );
                }
            }

        }
    }


    protected void addExplode(int x, int y) {
        // 添加爆炸效果
        Explode explode = ExplodesPool.get();
        explode.setX(x);
        explode.setY(y);
        explode.setVisible(true);
        explode.setIndex(0);
        explodes.add(explode);
    }

    /**
     * 坦克收到伤害
     * @param bullet
     */
    protected void hurt(Bullet bullet) {
        int atk = bullet.getAtk();
        hp -= atk;
        if (hp <= 0) {
            hp = 0;
            die();
        }
    }

    // 坦克死亡需要处理的内容

    /**
     * 绘制当前的爆炸效果
     * @param g
     */
    public void drawExplodes(Graphics g) {
        for (Explode explode : explodes) {
            explode.draw(g);
        }
        // 将不可见的对象 归还到对象池
        for (int i = 0; i < explodes.size(); i++) {
            if (!explodes.get(i).isVisible()){
                Explode explode = explodes.remove(i);
                i--;
                ExplodesPool.theReturn(explode);
            }
        }
    }

    /**
     * 绘制坦克的名字
     */
    protected void drawName(Graphics graphics) {
        graphics.setColor(color);
        graphics.setFont(Constant.TANK_NAME_FONT);
        graphics.drawString(name, x - RADIUS, (int)(y - RADIUS*1.5));
    }

    protected abstract void die();

    /**
     * 坦克的回退的方法
     */
    public void back() {
        x = preX;
        y = preY;
//        this.setState(STATE_STAND);
    }



    class BloodBar {
        public static final int BAR_LENGTH = (int)(RADIUS*(2.25));
        public static final int BAR_HEIGHT = (int)(RADIUS/5);
        public void draw(Graphics g) {
            g.setColor(Color.YELLOW);
            // 填充底色
            g.fillRect(x - RADIUS, y - RADIUS - BAR_HEIGHT - 2, BAR_LENGTH,BAR_HEIGHT);

            g.setColor(Color.RED);
            // 红色的当前血量
            g.fillRect(x - RADIUS, y - RADIUS - BAR_HEIGHT - 2, hp * BAR_LENGTH / DEFAULT_HP, BAR_HEIGHT);
            g.setColor(Color.WHITE);

            g.drawRect(x - RADIUS, y - RADIUS - BAR_HEIGHT - 2, BAR_LENGTH,BAR_HEIGHT);
        }
    }

    public  boolean isDie() {
        return hp <= 0;
    }

    /**
     * 坦克销毁时 处理坦克的所有子弹
     */
    public void bulletsReturn() {
        for (Bullet bullet : bullets) {
            BulletsPool.theReturn(bullet);
        }
        bullets.clear();
    }

    // 坦克的子弹和 地图所有 块的 碰撞
    public void bulletsCollideMapTiles(List<MapTile> tiles) {
        for (MapTile tile : tiles) {
            if(tile.isCollide(bullets)) {
                // 添加爆炸效果
                addExplode(tile.getX() + MapTile.tileW/2,tile.getY() + MapTile.tileW/2);
                // 设置地图块进行销毁
                if(tile.getTileType() == MapTile.TILE_TYPE1 || tile.getTileType() == MapTile.TILE_TYPE0) {
                    tile.setVisible(false);
                    // 归还对象池
                    MapTilePool.theReturn(tile);
                }
                // 当home被击毁后 一秒钟切换到游戏结束的画面
                if(tile.isHouse()) {
                    delayToOver(1000);
                }
            }
        }
    }

    /**
     * 延迟切换到游戏结束画面
     * @param seconds
     */
    protected void delayToOver(int seconds) {
        new Thread(){
            public void run() {
                try {
                    Thread.sleep(seconds);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                GameFrame.setGameState(Constant.STATE_OVER);
            }
        }.start();
    }

    /**
     * 从Tile提取八个点 判断 八个点中是否存在任意一个点 与坦克碰撞
     * @param
     * @return
     */
    public boolean isCollideTile(List<MapTile> mapTiles) {
        for (MapTile mapTile : mapTiles) {
            int tileX = mapTile.getX();
            int tileY = mapTile.getY();
            int r = MapTile.tileW/2;
            boolean collide0 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileX += r;
            boolean collide1 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileX += r;
            boolean collide2 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileY += r;
            boolean collide3 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileY += r;
            boolean collide4 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileX -= r;
            boolean collide5 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileX -= r;
            boolean collide6 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            tileY -= r;
            boolean collide7 = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide0 || collide1 || collide2 || collide3 || collide4 || collide5 || collide6 || collide7) {
                return true;
            }
        }
        return false;
    }

}
